#include "strategy.hpp"
#include "lines.hpp"
#include "money-tree.hpp"
#include "tjm_action.hpp"
#include "types.h"
#include "udp.h"
#include <cmath>
#include <cstdlib>

static const price_t Error_For_Golden_Point = 0.02;
static const price_t NEAR_THE_LINE = 10;
extern UdpClient* g_uc;

namespace Trade {

/*
      |\      _,,,---,,_
ZZZzz /,`.-'`'    -.  ;-;;,_
     |,4-  ) )-,_. ,\ (  `'-'
    '---''(_/--'  `-'\_)  Strategy Class
*/

risk_t
Strategy::estimate_this_dir_risk(const dir_t d, const case_t confused) noexcept
{
  return -std::abs(HPNOW - VO->lines.get_line2_price(-d));
}

price_t
Strategy::get_current_revune() noexcept
{
  return (0);
}

case_t
Strategy::retrive_confused_case() const noexcept
{
  case_t cno = 0;
  if (VO->flv_79.d_near_10 != VO->flv_79.d_far_10 ||
      VO->flv_79.d_near_10 != VO->flv_79.d_far_rt ||
      VO->flv_79.d_near_10 != VO->flv_79.d_near_rt ||
      VO->flv_79.d_far_10 != VO->flv_79.d_far_rt)
    cno |= CASE_CNFSD_FORCE_NEAR_FAR;
  if (VO->predicted_far_dir() != VO->predicted_near_dir())
    cno |= CASE_CNFSD_PREDICTED_NEAR_FAR;
  if (VO->flv_79.d_near_10 == VO->flv_79.d_near_rt &&
      VO->flv_79.d_near_10 != VO->predicted_near_dir())
    cno |= CASE_CNFSD_SOLVED_FORCE_NEAR;
  return cno;
}

/*
 -------------the line----------------------
  |                                            going down
  |       ----------* the_pnt
 all-h    |              ---- * Golden point      |
  |     now-h                                     |
  |       |                                      \|/
  |       |                                       `
 ------------- opposite line ----------------


 -------------opposite line------------------
  |
  |
  |                                               ^
 all-h                                           /|\
  |                  ---- * Golden point          |
  |       | ----------* the_pnt                   |
  |     now-h                                 going up
 ---------------- the line ------------------
*/

bool
Strategy::is_near_golden_point(const dir_t d,
                               const Lines* l,
                               const price_t hp) const noexcept
{
  // !! ATTENTION !! the-line's direction is -d //
  auto the_line = l->get_line1_price(-d);
  auto the_oppo_line = l->get_line2_price(d);
  auto all_height = std::abs(the_line - the_oppo_line);
  bool yes = 0;
  if (d < 0) {
    auto golden_height = all_height * phi;
    auto now_height = hp - the_oppo_line;
    yes = (now_height > golden_height * (1 - Error_For_Golden_Point));
  } else {
    auto golden_height = all_height * ppi;
    auto now_height = hp - the_line;
    yes = (now_height < golden_height * (1 + Error_For_Golden_Point));
  }

  return yes;
}

/*
 -------------the line----------------------
  |                                            going down
  |                                               |
  |                                               |
  |                                              \|/
  |                                               `
 ------------- opposite line ----------------


 -------------opposite line------------------
  |                                               ^
  |                                              /|\
  |                                               |
  |                                               |
  |                                            going up
 ---------------- the line ------------------
*/
bool
Strategy::is_near_oppo_line2(const dir_t d,
                             const Lines& l,
                             const price_t hp) const noexcept
{
  auto the_line = VO->lines.get_line2_price(-d);
  return (std::abs(hp - the_line) < NEAR_THE_LINE);
}

int
Strategy::close_position(const int part_of_all) noexcept
{
  int vol = MOCKIF.mock_query_position_volume(TOM_DIR);
  if (vol % part_of_all != 0)
    vol /= part_of_all;
  if (vol)
    do_something();
  return vol;
}

} // namespace Trade
